PSCI: Add pwr_domain_pwr_down_wfi() hook in plat_psci_ops
authorSoby Mathew <[email protected]>
Wed, 27 Apr 2016 13:46:28 +0000 (14:46 +0100)
committerSoby Mathew <[email protected]>
Wed, 25 May 2016 13:00:00 +0000 (14:00 +0100)
This patch adds a new optional platform hook `pwr_domain_pwr_down_wfi()` in
the plat_psci_ops structure. This hook allows the platform to perform platform
specific actions including the wfi invocation to enter powerdown. This hook
is invoked by both psci_do_cpu_off() and psci_cpu_suspend_start() functions.
The porting-guide.md is also updated for the same.

This patch also modifies the `psci_power_down_wfi()` function to invoke
`plat_panic_handler` incase of panic instead of the busy while loop.

Fixes ARM-Software/tf-issues#375

Change-Id: Iba104469a1445ee8d59fb3a6fdd0a98e7f24dfa3

docs/porting-guide.md
include/bl31/services/psci.h
services/std_svc/psci/psci_entry.S
services/std_svc/psci/psci_off.c
services/std_svc/psci/psci_suspend.c

index 0cd36134f4b2dd3b0b88317260d673f0729d462c..8947defb08a6482a7f431ddbdd9203830dc0fb14 100644 (file)
@@ -1715,6 +1715,22 @@ latter case, the power domain is expected to save enough state so that it can
 resume execution by restoring this state when its powered on (see
 `pwr_domain_suspend_finish()`).
 
+#### plat_psci_ops.pwr_domain_pwr_down_wfi()
+
+This is an optional function and, if implemented, is expected to perform
+platform specific actions including the `wfi` invocation which allows the
+CPU to powerdown. Since this function is invoked outside the PSCI locks,
+the actions performed in this hook must be local to the CPU or the platform
+must ensure that races between multiple CPUs cannot occur.
+
+The `target_state` has a similar meaning as described in the `pwr_domain_off()`
+operation and it encodes the platform coordinated target local power states for
+the CPU power domain and its parent power domain levels. This function must
+not return back to the caller.
+
+If this function is not implemented by the platform, PSCI generic
+implementation invokes `psci_power_down_wfi()` for power down.
+
 #### plat_psci_ops.pwr_domain_on_finish()
 
 This function is called by the PSCI implementation after the calling CPU is
index acf07869f1b165d8429f267ba4c47ce1e3fc596c..95e77809b4de987fe30fea536c4b1f1ce5a6b204 100644 (file)
@@ -265,6 +265,8 @@ typedef struct plat_psci_ops {
        void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
        void (*pwr_domain_suspend_finish)(
                                const psci_power_state_t *target_state);
+       void (*pwr_domain_pwr_down_wfi)(
+                               const psci_power_state_t *target_state) __dead2;
        void (*system_off)(void) __dead2;
        void (*system_reset)(void) __dead2;
        int (*validate_power_state)(unsigned int power_state,
index 5f4f91c59f2b702962fbd6c4cb0870b2fde941da..f8c0afa255a72f1b7899be160588a2e22a6d9db0 100644 (file)
@@ -106,7 +106,6 @@ endfunc psci_entrypoint
 func psci_power_down_wfi
        dsb     sy              // ensure write buffer empty
        wfi
-wfi_spill:
-       b       wfi_spill
+       bl      plat_panic_handler
 endfunc psci_power_down_wfi
 
index cef66689e8e9d38bd890ca5ba8747d980f156240..686666d54f213078d15f79e4278914a31c6dc79f 100644 (file)
@@ -138,11 +138,16 @@ exit:
                dsbish();
                inv_cpu_data(psci_svc_cpu_data.aff_info_state);
 
-               /*
-                * Enter a wfi loop which will allow the power controller to
-                * physically power down this cpu.
-                */
-               psci_power_down_wfi();
+               if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi) {
+                       /* This function must not return */
+                       psci_plat_pm_ops->pwr_domain_pwr_down_wfi(&state_info);
+               } else {
+                       /*
+                        * Enter a wfi loop which will allow the power
+                        * controller to physically power down this cpu.
+                        */
+                       psci_power_down_wfi();
+               }
        }
 
        return rc;
index 367bb32a6e7e874f85f6b752cf0167f58d3dec26..8c6ab6b40d999b35614f5e10d62da6219b06d905 100644 (file)
@@ -189,8 +189,13 @@ exit:
        if (skip_wfi)
                return;
 
-       if (is_power_down_state)
-               psci_power_down_wfi();
+       if (is_power_down_state) {
+               /* The function calls below must not return */
+               if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi)
+                       psci_plat_pm_ops->pwr_domain_pwr_down_wfi(state_info);
+               else
+                       psci_power_down_wfi();
+       }
 
        /*
         * We will reach here if only retention/standby states have been